package com.example.cinemasystemv2.service;

import com.example.cinemasystemv2.entity.Order;
import com.example.cinemasystemv2.entity.Screening;
import com.example.cinemasystemv2.repository.OrderRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.List;
import java.util.Optional;

@Service
public class OrderService {
    
    @Autowired
    private OrderRepository orderRepository;
    
    @Autowired
    private SystemLogService systemLogService;
    
    public List<Order> getAllOrders() {
        return orderRepository.findAll();
    }
    
    public Optional<Order> getOrderById(String orderId) {
        return orderRepository.findById(orderId);
    }
    
    public Optional<Order> getOrderByOrderId(String orderId) {
        return orderRepository.findById(orderId);
    }
    
    public List<Order> getOrdersByUsername(String username) {
        return orderRepository.findByUsername(username);
    }
    
    public List<Order> getOrdersByScreening(Screening screening) {
        return orderRepository.findByScreening(screening);
    }
    
    public List<Order> getTodayOrders() {
        LocalDateTime startOfDay = LocalDateTime.now().toLocalDate().atStartOfDay();
        LocalDateTime endOfDay = startOfDay.plusDays(1).minusSeconds(1);
        return orderRepository.findByDateRange(startOfDay, endOfDay);
    }
    
    public List<Order> getWeekOrders() {
        LocalDateTime startOfWeek = LocalDateTime.now().minusDays(7).toLocalDate().atStartOfDay();
        LocalDateTime endOfWeek = LocalDateTime.now();
        return orderRepository.findByDateRange(startOfWeek, endOfWeek);
    }
    
    public List<Order> getMonthOrders() {
        LocalDateTime startOfMonth = LocalDateTime.now().minusDays(30).toLocalDate().atStartOfDay();
        LocalDateTime endOfMonth = LocalDateTime.now();
        return orderRepository.findByDateRange(startOfMonth, endOfMonth);
    }
    
    public List<Order> getOrdersByDateRange(LocalDateTime startTime, LocalDateTime endTime) {
        return orderRepository.findByDateRange(startTime, endTime);
    }
    
    public Order saveOrder(Order order) {
        if (order.getOrderTime() == null) {
            order.setOrderTime(LocalDateTime.now());
        }
        Order savedOrder = orderRepository.save(order);
        systemLogService.log("订单创建: " + order.getOrderId() + " - " + order.getUsername(), 
                           order.getUsername(), "CREATE_ORDER");
        return savedOrder;
    }
    
    public Order createOrder(String username, Screening screening, int row, int seat, double amount) {
        // 检查座位是否已被预订
        if (isSeatTaken(screening, row, seat)) {
            throw new IllegalArgumentException("该座位已被预订");
        }
        
        String orderId = generateOrderId();
        Order order = new Order(orderId, username, screening, row, seat, amount, LocalDateTime.now());
        return saveOrder(order);
    }
    
    public boolean isSeatTaken(Screening screening, int row, int seat) {
        List<Order> existingOrders = orderRepository.findBySeat(screening, row, seat);
        return !existingOrders.isEmpty();
    }
    
    public Order refundOrder(String orderId) {
        Optional<Order> orderOpt = orderRepository.findById(orderId);
        if (orderOpt.isPresent()) {
            Order order = orderOpt.get();
            
            if (order.isRefunded()) {
                throw new IllegalArgumentException("订单已退款");
            }
            
            // 检查退票时间限制（开场前30分钟）
            LocalDateTime screeningTime = order.getScreening().getStartTime();
            LocalDateTime now = LocalDateTime.now();
            long minutesUntilScreening = ChronoUnit.MINUTES.between(now, screeningTime);
            
            if (minutesUntilScreening < 30) {
                throw new IllegalArgumentException("开场前30分钟内不能退票");
            }
            
            // 计算退款金额（可以根据业务规则调整）
            double refundAmount = order.getAmount() * 0.9; // 扣除10%手续费
            
            order.setRefunded(true);
            order.setRefundTime(LocalDateTime.now());
            order.setRefundAmount(refundAmount);
            
            Order refundedOrder = orderRepository.save(order);
            systemLogService.log("订单退款: " + orderId + " - 退款金额: " + refundAmount, 
                               order.getUsername(), "REFUND_ORDER");
            return refundedOrder;
        }
        throw new IllegalArgumentException("订单不存在");
    }
    
    public Double getTotalSalesByDate(LocalDateTime date) {
        Double total = orderRepository.getTotalSalesByDate(date);
        return total != null ? total : 0.0;
    }
    
    public Double getTotalSalesByDateRange(LocalDateTime startTime, LocalDateTime endTime) {
        Double total = orderRepository.getTotalSalesByDateRange(startTime, endTime);
        return total != null ? total : 0.0;
    }
    
    public long getSoldTicketsCount(Screening screening) {
        return orderRepository.countSoldTickets(screening);
    }
    
    public List<Order> getRefundedOrders() {
        return orderRepository.findByIsRefunded(true);
    }
    
    public List<Order> getActiveOrders() {
        return orderRepository.findByIsRefunded(false);
    }
    
    private String generateOrderId() {
        return "ORD" + System.currentTimeMillis() + (int)(Math.random() * 1000);
    }
    
    // 获取座位占用情况
    public boolean[][] getSeatOccupancy(Screening screening) {
        int rows = screening.getRoom().getNumRows();
        int seatsPerRow = screening.getRoom().getSeatsPerRow();
        boolean[][] occupancy = new boolean[rows][seatsPerRow];
        
        List<Order> orders = getOrdersByScreening(screening);
        for (Order order : orders) {
            if (!order.isRefunded()) {
                occupancy[order.getRow() - 1][order.getSeat() - 1] = true;
            }
        }
        
        return occupancy;
    }
    
    // 获取已占用座位列表（字符串格式）
    public List<String> getOccupiedSeatsByScreening(Long screeningId) {
        List<String> occupiedSeats = new java.util.ArrayList<>();
        
        // 根据screeningId获取screening对象
        // 这里需要注入ScreeningService或者通过Repository直接查询
        // 为了简化，我们假设可以通过某种方式获取到screening
        List<Order> orders = orderRepository.findAll().stream()
            .filter(order -> order.getScreening().getId().equals(screeningId) && !order.isRefunded())
            .collect(java.util.stream.Collectors.toList());
        
        for (Order order : orders) {
            // 将行号转换为字母，座位号保持数字
            char rowLetter = (char) ('A' + order.getRow() - 1);
            String seatCode = rowLetter + String.valueOf(order.getSeat());
            occupiedSeats.add(seatCode);
        }
        
        return occupiedSeats;
    }
}